package com.qipay.admin.withdraw.controller;

import com.qipay.admin.BaseController;
import com.qipay.admin.tags.PageModel;
import com.qipay.admin.utils.DESUtil;
import com.qipay.admin.withdraw.service.GoogleAuthenticator;
import com.qipay.admin.withdraw.service.WithdrawAnother2Service;
import com.qipay.admin.withdraw.service.WithdrawAnotherService;
import com.qipay.admin.withdraw.service.WithdrawLogicService;
import com.qipay.admin.withdraw.vo.CountWithdrawInfoVo;
import com.qipay.admin.withdraw.vo.WithdrawExportVo;
import com.qipay.admin.withdraw.vo.WithdrawVo;
import com.qipay.baas.model.Cp;
import com.qipay.baas.model.CpWithdrawTradlog;
import com.qipay.baas.model.WhiteIps;
import com.qipay.cp.CpService;
import com.qipay.excel.service.ExcelService;
import com.qipay.excel.service.ExcelUtils;
import com.qipay.holiday.service.HolidayService;
import com.qipay.ips.service.IpsService;
import com.qipay.scalar.type.BankEnum;
import com.qipay.security.UserDetailsServiceImpl;
import com.qipay.sms.config.AliyunSMSTemplateEnum;
import com.qipay.sms.utils.CodeCacheUtils;
import com.qipay.sp.SpConfigService;
import com.qipay.user.entity.UserLevel;
import com.qipay.utils.DateUtils;
import com.qipay.utils.MD5Util;
import com.qipay.utils.Result;
import com.qipay.withdraw.config.WithdrawStateEnum;
import com.qipay.withdraw.service.WithdrawService;
import io.jsonwebtoken.lang.Assert;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * Creator: Yao
 * Date:    2017/9/27
 * For:
 * Other:
 */
@Controller
@RequestMapping("/withdraw")
public class WithdrawController extends BaseController {

    @Autowired
    WithdrawLogicService withdrawLogicService;

    @Autowired
    WithdrawAnotherService withdrawAnotherService;

    @Autowired
    WithdrawAnother2Service withdrawAnother2Service;
    @Autowired
    HolidayService holidayService;

    private String msg;

    @Autowired
    WithdrawService withdrawService;
    @Autowired
    ExcelUtils excelUtils;
    @Autowired
    CodeCacheUtils codeCacheUtils;
    @Autowired
    CpService cpService;
    @Autowired
    SpConfigService spConfigService;


    private final static String pattern = "\\d{4}-\\d{1,2}-\\d{1,2}";


    @RequestMapping(value = {"", "/", "/cp", "/admin"}, method = RequestMethod.GET)
    public ModelAndView listByCpId(
            @AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser,
            @RequestParam(value = "cpId", required = false, defaultValue = "") Long cpId,
            @RequestParam(value = "orderNo", required = false, defaultValue = "") String orderNo,
            @RequestParam(value = "state", required = false, defaultValue = "") Byte state,
            @RequestParam(value = "from", required = false, defaultValue = "") String from,
            @RequestParam(value = "to", required = false, defaultValue = "") String to,
            @RequestParam(value = "p", required = false, defaultValue = "1") int p,
            @RequestParam(value = "pz", required = false, defaultValue = "10") int pz) throws ParseException, UnsupportedEncodingException {

        // check
        Assert.notNull(loginUser);
        UserLevel level = loginUser.getLevel();
        List<WithdrawVo> lst = null;
        PageModel pageModel = new PageModel();
        long total = 0;
        CountWithdrawInfoVo countWithdrawInfoVo = null;
        p = p < 1 ? 1 : p;
        pz = pz <= 0 ? 10 : pz;

        // init
        ModelAndView view = createModelAndView("withdraw-lst");
        to = DateUtils.checkElseNow(to);
        if (StringUtils.isNotBlank(from)) {
            Assert.isTrue(from.matches(pattern), "指定开始日期格式有误，非 YYYY-MM-DD 形式");
        } else {
            from = to;
        }

        // query

        if (!level.equals(UserLevel.ADMIN)) {
            cpId = Long.valueOf(loginUser.getUsername());
        }
        total = withdrawLogicService.count(cpId, orderNo, state, from, to);
        if (total > 0) {
            lst = withdrawLogicService.list(cpId, orderNo, state, from, to, p, pz);
        }
        //统计行信息
        countWithdrawInfoVo = withdrawLogicService.countInfo(cpId, orderNo, state, from, to);
        // url.init
        String url = "?";
        if (StringUtils.isNotBlank(from)) {
            url += String.format("&from=%s", URLEncoder.encode(from, "utf8"));
        }
        if (StringUtils.isNotBlank(to)) {
            url += String.format("&to=%s", URLEncoder.encode(to, "utf8"));
        }
        if (cpId != null) {
            url += String.format("&cpId=%s", URLEncoder.encode(cpId.toString(), "utf8"));
        }
        if (state != null) {
            url += String.format("&state=%s", URLEncoder.encode(state.toString(), "utf8"));

        }
        if (!"?".equalsIgnoreCase(url)) {
            pageModel.setUrl(url);
        }

        // fill
        withdrawLogicService.initConfig(view, loginUser);
        view.addObject("total", total);
        view.addObject("lst", lst);
        view.addObject("level", level);
        view.addObject("from", from);
        view.addObject("orderNo", orderNo);
        view.addObject("to", to);
        view.addObject("cpId", cpId);
        view.addObject("state", state);
        view.addObject("states", mapState());
        view.addObject("countWithdrawInfoVo", countWithdrawInfoVo);
        pageModel.setPage(p);
        pageModel.setPageSize(pz);
        pageModel.setTotal(total);
        view.addObject("page", pageModel);

        return view;
    }

    @Autowired
    ExcelService excelService;

    //导出
    @RequestMapping(value = "/export", method = RequestMethod.GET)
    public String export(
            @AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser,
            @RequestParam(value = "cpId", required = false, defaultValue = "") Long cpId,
            @RequestParam(value = "orderNo", required = false, defaultValue = "") String orderNo,
            @RequestParam(value = "state", required = false, defaultValue = "") Byte state,
            @RequestParam(value = "from", required = false, defaultValue = "") String from,
            @RequestParam(value = "to", required = false, defaultValue = "") String to,
            HttpServletResponse resp
    ) throws IOException, ParseException {
        // check
        Assert.notNull(loginUser);
        UserLevel level = loginUser.getLevel();
        List<WithdrawExportVo> lst = null;
        long total = 0;
        // init
        ModelAndView view = createModelAndView("withdraw-lst");
        to = DateUtils.checkElseNow(to);
        if (StringUtils.isNotBlank(from)) {
            Assert.isTrue(from.matches(pattern), "指定开始日期格式有误，非 YYYY-MM-DD 形式");
        } else {
            from = to;
        }
        // query
        if (!level.equals(UserLevel.ADMIN)) {
            cpId = Long.valueOf(loginUser.getUsername());
        }
        total = withdrawLogicService.count(cpId, orderNo, state, from, to);
        if (total > 0) {
            lst = withdrawLogicService.exportList(cpId, orderNo, state, from, to, 1, 10000);
        }
        //1.初始化excel表格
        initExcel();
        //2.开始在excel表里面存入数据
        String[] tableHeader = new String[]{"ID", "商户ID", "商户名称", "银行", "支行", "卡号", "姓名", "金额", "手续费", "到账金额", "提现类型", "代付类型", "状态", "备注"
                , "申请时间", "出款时间"};
        initParam("提现代付列表");
        daochu(lst, tableHeader);
        finishExcel("提现代付 列表", resp);

        return null;
    }

    @RequestMapping(value = "/{withdrawId:\\d+}", method = RequestMethod.GET)
    public ModelAndView get(
            @AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser,
            @PathVariable(name = "withdrawId", required = true) Long withdrawId) {
        // check login
        Assert.notNull(loginUser);

        // init
        WithdrawVo withdraw = null;
        ModelAndView view = createModelAndView(0 == withdrawId ? "withdraw-apply" : "withdraw-detail");

        //
        if (null != withdrawId && 0 != withdrawId) {
            withdraw = withdrawLogicService.get(withdrawId);
        } else {
            withdraw = new WithdrawVo();
            withdraw.setId(0l);
            withdrawLogicService.initInfo(view, loginUser);
        }
        view.addObject("detail", withdraw);
        view.addObject("isHoliday", holidayService.check(new Date()));
        withdrawLogicService.fillApplyArgs(view, loginUser);

        //以下操作主要是为了避免刷新页面
        //清除缓存
        codeCacheUtils.invalidateCode(loginUser.getUsername(), AliyunSMSTemplateEnum.MONYUNVALID.getCode());
        //验证码
        String validCode = codeCacheUtils.generateValidCode(loginUser.getUsername(), AliyunSMSTemplateEnum.MONYUNVALID.getCode());
        view.addObject("validCode", validCode);

        return view;
    }

    /**
     * 提现、代付申请
     *
     * @param loginUser
     * @param withdraw
     * @return
     * @throws ParseException
     * @throws UnsupportedEncodingException
     */
    @RequestMapping(value = {"", "/"}, method = RequestMethod.POST)
    public ModelAndView save(
            @AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser,
            WithdrawVo withdraw) throws ParseException, UnsupportedEncodingException {
        String from = DateUtils.checkElseNow("");
        String myValidCode = codeCacheUtils.getValidCode(loginUser.getUsername(), AliyunSMSTemplateEnum.MONYUNVALID.getCode());
        if (withdraw.getValidCode().equals(myValidCode)) {
            //清除缓存
            codeCacheUtils.invalidateCode(loginUser.getUsername(), AliyunSMSTemplateEnum.MONYUNVALID.getCode());
        } else {
            return listByCpId(loginUser, null, null, (byte) -1, from, from, 1, 10);
        }

        // save
        withdrawLogicService.save(loginUser, withdraw);
        Long cpId = null;

        return listByCpId(loginUser, cpId, null, (byte) -1, from, from, 1, 10);
    }

    /**
     * 查询是否两分钟之内有验证码，有则拒绝发送
     *
     * @param loginUser
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/queryValid", method = RequestMethod.PUT)
    public Result queryValid(
            @AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser) {
        Assert.notNull(loginUser);
        Cp cp = cpService.getOneById(Long.parseLong(loginUser.getUsername().equals("admin") ? String.valueOf(loginUser.getPid()) : loginUser.getUsername()));
        Assert.notNull(cp, "未找到指定 CP");
        String phone = cp.getBindMobile();
        String validCode = codeCacheUtils.getValidCode(phone, AliyunSMSTemplateEnum.MONYUNVALID.getCode());

        Result result = new Result<>();
        if (StringUtils.isBlank(validCode)) {
            result.setCode(200);
        } else {
            result.setCode(-1);
        }
        return result;
    }

    @ResponseBody
    @RequestMapping(value = "/{withdrawId:\\d+}/cancel", method = RequestMethod.PUT)
    public Result cancel(
            @AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser,
            @PathVariable(name = "withdrawId", required = true) Long withdrawId) {

        // init
        Result result = new Result<>();

        // logic
        try {
            withdrawLogicService.cancel(loginUser, withdrawId);
            result.setCode(200);
        } catch (Exception e) {
            result.setCode(-1);
            result.setMsg(e.getMessage());
        }

        return result;
    }

    @ResponseBody
    @RequestMapping(value = "/{withdrawId:\\d+}/unPass", method = RequestMethod.PUT)
    public Result unPass(
            @AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser,
            @PathVariable(name = "withdrawId", required = true) Long withdrawId,
            @RequestParam(name = "remark", required = true) String remark) {
        // init
        Result result = new Result<>();
        // logic
        try {
            withdrawLogicService.unPass(loginUser, withdrawId, remark);
            result.setCode(200);
        } catch (Exception e) {
            result.setCode(-1);
            result.setMsg(e.getMessage());
        }

        return result;
    }

    @ResponseBody
    @RequestMapping(value = "/{withdrawId:\\d+}/handPass", method = RequestMethod.PUT)
    public Result handPass(
            @AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser,
            @PathVariable(name = "withdrawId", required = true) Long withdrawId,
            @RequestParam(name = "remark", required = true) String remark) {

        // init
        Result result = new Result<>();

        // logic
        try {
            withdrawLogicService.handPass(loginUser, withdrawId, remark);
            result.setCode(200);
        } catch (Exception e) {
            result.setCode(-1);
            result.setMsg(e.getMessage());
        }

        return result;
    }

    @ResponseBody
    @RequestMapping(value = "/valid", method = RequestMethod.GET)
    public Result valid(
            @AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser) {
        // init
        Result result = new Result<>();
        // logic
        try {
            result.setData(withdrawLogicService.valid(loginUser));
            result.setCode(200);
        } catch (Exception e) {
            result.setCode(-1);
            result.setMsg(e.getMessage());
        }

        return result;
    }


    /**
     * 确认通过提现审核，代付（非手动出款）
     *
     * @param loginUser
     * @param withdrawId
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/{withdrawId:\\d+}/pass", method = RequestMethod.PUT)
    public Result pass(
            @AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser,
            @PathVariable(name = "withdrawId", required = true) Long withdrawId,
            @RequestParam(name = "agentNo", required = true) String agentNo,
            @RequestParam(value = "trxType", required = true, defaultValue = "") String trxType,
            @RequestParam(value = "accountType", required = true, defaultValue = "") String accountType) throws UnsupportedEncodingException {
        CpWithdrawTradlog cpWithdrawTradlog = withdrawService.get(withdrawId);

        Result result = new Result<>();

        return result;
    }


    private Map<Byte, String> mapState() {
        // init
        Map<Byte, String> map = new TreeMap<>();

        // fill
        for (WithdrawStateEnum p : WithdrawStateEnum.values()) {
            map.put(p.getState(), p.getInfo());
        }
        map.put((byte) -1, "所有");
        //
        map.remove((byte) 1);
        map.remove((byte) 3);
        map.remove((byte) 4);
        map.remove((byte) 2);

        map.put((byte) 2, "成功");
        map.put((byte) -2, "失败");
        return map;
    }


    /**
     * 乐娱--代付
     *
     * @param loginUser
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/ly1", method = RequestMethod.GET)
    public ModelAndView toAnotherApply(@AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser) throws Exception {

        ModelAndView view = createModelAndView("another-apply");
        view.addObject("level", UserLevel.ADMIN);
        Map<String, Object> paramsHead = new HashMap<>();
        paramsHead.put("appId", "1001");
        paramsHead.put("version", "1.0");
        paramsHead.put("reqType", "transfer_query_wallet_request");
        paramsHead.put("mchid", "111000000000056");//商户号/机构代码
        paramsHead.put("reqNo", System.currentTimeMillis() + "");//请求流水号
        paramsHead.put("signType", "RSA1");

        Map<String, Object> paramsData = new HashMap<>();
        paramsData.put("bCode", "111000000000056");
        paramsData.put("walletId", "2465Y5D067rSyv111");
        try {
            //查询余额
            Map<String, Object> responseMap = withdrawAnotherService.findDfBalance(paramsHead, paramsData);
            if (responseMap != null && "0".equals(responseMap.get("result_code"))) {
                view.addObject("QQAllBalance", new BigDecimal(String.valueOf(responseMap.get("allAmt"))).divide(new BigDecimal("100")));
                view.addObject("QQAllBrawableBalance", new BigDecimal(String.valueOf(responseMap.get("freezeAmt"))).divide(new BigDecimal("100")));
                view.addObject("QQAllTransferBalance", new BigDecimal(String.valueOf(responseMap.get("transferAmt"))).divide(new BigDecimal("100")));
            } else {
                view.addObject("msg", responseMap.get("message"));
            }
            if (msg != null) {
                view.addObject("msg", msg);
                msg = null;
            }
        } catch (Exception e) {

        }
        return view;
    }


    private static String pubkey_21 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiwjw0sjadTinb7p8y6w02dg3yAwMJB/V3DI6bv2RZH/oJxRFha3u9BKCkIlwQYBCyWb2PpJDXc7CLDX8PRjxNRVT2XvDYA/erTsMcWXC9yl8MJby2Cx9oz6fgmVGBPoeYDZTMSS8aQcCOaHliEyyZPwYLv14D5hhOr1IeFcqKFwIDAQAB";
    private static String pubkey_22 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCZJTD5yDSJch6KLmaH/92XMw6SiFRg7UQdZpKxOIxhQX+4TDkVbcbxMKcU4fPRdZV4hFnkPnbwBPIkgoQUMhKbZ8BF8Q48tcRHSbWk6MPMLeYOGigFwFFFc9aUb3aaufJd6dn9ZRzNt8md2ljx050oM2RsQ5lhRs3isKy4S3u0qwIDAQAB";
    private static String pubkey_24 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYttr13vMRvZOUnZmLZHFa4ZTYfHxPe6EvYlnojaC/clLlcDa7CvJp+nELi9WPGYwoQfpSYYdGj4L5nnUvD5oLq4JZRH333xaY5dlbo49AlADmd8unZXvzTpS9aTvq3q42u9G+mg5o8vdSwjSH2csoyCYlTx31X3YDPR132nKlRwIDAQAB";

    /**
     * 快捷--代付
     *
     * @param loginUser
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/kj", method = RequestMethod.GET)
    public ModelAndView toAnotherApply2(@AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser) throws Exception {
        ModelAndView view = createModelAndView("another-apply2");
        view.addObject("level", UserLevel.ADMIN);
        try {
            //查询余额
            Map<String, Object> responseMap = withdrawAnother2Service.findDfBalance("288870000021", "2B2E2B6FBCBF43C6BBD178A67D20E86F", pubkey_21);
            Map<String, Object> responseMap2 = withdrawAnother2Service.findDfBalance("288870000022", "1684F93D5B6540F09F88ED0201F846C6", pubkey_22);
            Map<String, Object> responseMap3 = withdrawAnother2Service.findDfBalance("288870000024", "AB6078FD5CFF4053A8DFA8B1CAE11574", pubkey_24);
            if (responseMap != null && "0000".equals(responseMap.get("retcode"))) {
                view.addObject("QQAllBalance", responseMap.get("balance"));
            }
            if (responseMap != null && "0000".equals(responseMap2.get("retcode"))) {
                view.addObject("QQAllBalance2", responseMap2.get("balance"));
            }
            if (responseMap != null && "0000".equals(responseMap3.get("retcode"))) {
                view.addObject("QQAllBalance3", responseMap3.get("balance"));
            }
        } catch (Exception e) {

        }
        if (msg != null) {
            view.addObject("msg", msg);
            msg = null;
        }
        return view;
    }



    /**
     * 企鹅--代付
     *
     * @param loginUser
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/qe", method = RequestMethod.GET)
    public ModelAndView toAnotherApply3(@AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser) throws Exception {
        ModelAndView view = createModelAndView("another-apply3");
        view.addObject("level", UserLevel.ADMIN);
        Map<String, Object> paramsData = new HashMap<>();
        paramsData.put("mercId", "OLP800250000001");
        String orderId = System.currentTimeMillis() + "";
        paramsData.put("mercOrderId", orderId);//请求流水号
        paramsData.put("md5value", MD5Util.sign("OLP800250000001" + orderId + "BP7lJUYPGyk30Yav1dbZ3freK", "utf-8"));

        try {
            //查询余额
            HashMap<String, String> responseMap = withdrawAnotherService.findQeBalance(paramsData);
            if (responseMap != null && "0".equals(responseMap.get("status"))) {
                view.addObject("QQAllBalance", new BigDecimal(responseMap.get("allMoney")).divide(new BigDecimal("100")));
                view.addObject("QQAllBrawableBalance", new BigDecimal(responseMap.get("t1Money")).divide(new BigDecimal("100")));
                view.addObject("QQAllTransferBalance", new BigDecimal(responseMap.get("djMoney")).divide(new BigDecimal("100")));
            } else {
                view.addObject("msg", responseMap.get("msg"));
            }
        } catch (Exception e) {

        }
        return view;
    }

    @ResponseBody
    @RequestMapping(value = "/{withdrawId:\\d+}/updateRemark", method = RequestMethod.PUT)
    public Result updateRemark(
            @AuthenticationPrincipal UserDetailsServiceImpl.LoginUserDetails loginUser,
            @PathVariable(name = "withdrawId", required = true) Long withdrawId,
            @RequestParam(name = "remark", required = true) String remark) {
        // init
        Result result = new Result<>();
        // logic
        try {
            CpWithdrawTradlog log = withdrawService.get(withdrawId);
            log.setRemark(remark);
            log.setFinishTime(new Date());
            withdrawService.update(log);
            result.setCode(200);
        } catch (Exception e) {
            result.setCode(-1);
            result.setMsg(e.getMessage());
        }

        return result;
    }

}
